package com.jackstraw.create.service.impl;

import com.jackstraw.create.param.ImportPackageMap;
import com.jackstraw.create.pojo.CreateInfo;
import com.jackstraw.create.pojo.FieldData;
import com.jackstraw.create.pojo.TableData;
import com.jackstraw.create.service.ICreateService;
import com.jackstraw.create.utils.DatabaseUtil;
import com.jackstraw.create.utils.DbColumnUtil;
import com.jackstraw.create.utils.VelocityUtil;
import org.apache.velocity.VelocityContext;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 版权所有： 稻草人
 * 所在包：com.jackstraw.create.service.impl
 * 文件名：
 * 项目：create
 * 功能描述：
 * 修改时间：2021-04-16 23:43
 *
 * @author jackstraw
 */
@Service
public class CreateServiceImpl implements ICreateService {

    @Override
    public void createFile(CreateInfo createInfo) {
        String tableList = createInfo.getTableList();
        String[] tableArr = tableList.split(",");
        // 生成文件
        for (String tableName : tableArr) {
            try {
                createSingleFile(createInfo, tableName);
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("--------------------------------- 创建失败 ： " + tableName);
            }
        }
    }

    /**
     * 单个文件创建
     *
     * @param createInfo
     * @param tableName
     * @throws Exception
     */
    private void createSingleFile(CreateInfo createInfo, String tableName) throws Exception {
        String packagePath = createInfo.getPackageName().replaceAll("\\.", "/");
        // 获取并注入数据map
        Map<String, Object> dataMap = buildDatabaseDataMap(tableName);
        injectMapData(createInfo, dataMap);
        // 构建VelocityContext
        VelocityContext context = VelocityUtil.buildVelocityContextByMap(dataMap);
        // 构建文件
        TableData table = (TableData) dataMap.get("table");
        Boolean index = createInfo.getIndex();
        Boolean editForm = createInfo.getEditForm();
        Boolean pojo = createInfo.getPojo();
        Boolean pojoVo = createInfo.getPojoVo();
        Boolean pojoDto = createInfo.getPojoDto();
        Boolean mapper = createInfo.getMapper();
        Boolean mapperXml = createInfo.getMapperXml();
        Boolean service = createInfo.getService();
        Boolean serviceImpl = createInfo.getServiceImpl();
        Boolean controller = createInfo.getController();
        // todo: 根据vm前缀 如果是 xxx.html.vm 生成 xxx.html, 如果是xxx.vue.vm 生成 xxx.vue
        if (index) {
            VelocityUtil.createFile(createInfo.getFolderPath() + "/" + packagePath + "/html/" + DbColumnUtil.upperFirstCase(DbColumnUtil.transUnderlineToCamel(tableName)), createInfo.getIndexTpName().substring(0, createInfo.getIndexTpName().lastIndexOf(".")), createInfo.getIndexTpName(), context);
        }
        if (editForm) {
            VelocityUtil.createFile(createInfo.getFolderPath() + "/" + packagePath + "/html/" + DbColumnUtil.upperFirstCase(DbColumnUtil.transUnderlineToCamel(tableName)), createInfo.getEditFormTpName().substring(0, createInfo.getEditFormTpName().lastIndexOf(".")), createInfo.getEditFormTpName(), context);
        }

        if (pojo) {
            VelocityUtil.createFile(createInfo.getFolderPath() + "/" + packagePath + "/" + createInfo.getPojoName(), table.getClassName() + ".java", createInfo.getPojoTptName(), context);
        }
        if (pojoVo) {
            VelocityUtil.createFile(createInfo.getFolderPath() + "/" + packagePath + "/" + createInfo.getPojoVoName(), table.getClassName() + "Vo.java", createInfo.getPojoVoTptName(), context);
        }
        if (pojoDto) {
            VelocityUtil.createFile(createInfo.getFolderPath() + "/" + packagePath + "/" + createInfo.getPojoDtoName(), table.getClassName() + "Dto.java", createInfo.getPojoDtoTptName(), context);
        }
        if (mapper) {
            VelocityUtil.createFile(createInfo.getFolderPath() + "/" + packagePath + "/" + createInfo.getMapperName(), table.getClassName() + "Mapper.java", createInfo.getMapperTptName(), context);
        }
        if (mapperXml) {
            VelocityUtil.createFile(createInfo.getFolderPath() + "/" + packagePath + "/" + createInfo.getMapperXmlName(), table.getClassName() + "Mapper.xml", createInfo.getMapperXmlTptName(), context);
        }
        if (service) {
            VelocityUtil.createFile(createInfo.getFolderPath() + "/" + packagePath + "/" + createInfo.getServiceName(), "I" + table.getClassName() + "Service.java", createInfo.getServiceTptName(), context);
        }
        if (serviceImpl) {
            VelocityUtil.createFile(createInfo.getFolderPath() + "/" + packagePath + "/" + createInfo.getServiceName() + "/" + createInfo.getServiceImplName(), table.getClassName() + "ServiceImpl.java", createInfo.getServiceImplTptName(), context);
        }
        if (controller) {
            VelocityUtil.createFile(createInfo.getFolderPath() + "/" + packagePath + "/" + createInfo.getControllerName(), table.getClassName() + "Controller.java", createInfo.getControllerTptName(), context);
        }
    }

    /**
     * 插入自定义模板映射值
     *
     * @param createInfo
     * @param dataMap
     */
    private void injectMapData(CreateInfo createInfo, Map<String, Object> dataMap) {
        dataMap.put("package", createInfo.getPackageName());
        dataMap.put("pojo", createInfo.getPojoName());
        dataMap.put("vo", createInfo.getPojoVoName());
        dataMap.put("dto", createInfo.getPojoDtoName());
        dataMap.put("mapper", createInfo.getMapperName());
        dataMap.put("mapperXml", createInfo.getMapperXmlName());
        dataMap.put("service", createInfo.getServiceName());
        dataMap.put("serviceImpl", createInfo.getServiceImplName());
        dataMap.put("controller", createInfo.getControllerName());
        dataMap.put("author", createInfo.getAuthorName());
        dataMap.put("createTime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        dataMap.put("serialVersionUID", (new Random().nextLong()) + "L");
        dataMap.put("projectName", createInfo.getProjectName() != null ? createInfo.getProjectName() : "");
        dataMap.put("copyRightName", createInfo.getCopyRightName() != null ? createInfo.getCopyRightName() : "");

        TableData table = (TableData) dataMap.get("table");
        StringBuffer pojoImport = new StringBuffer("");
        List<FieldData> fieldList = table.getFieldList();
        Set<String> fieldTypes = new HashSet<>();
        for (FieldData fieldData : fieldList) {
            fieldTypes.add(fieldData.getFieldType());
        }
        for (String fieldType : fieldTypes) {
            String importLine = ImportPackageMap.getImportLineByFieldType(fieldType);
            if (importLine != null) {
                pojoImport.append("import ");
                pojoImport.append(importLine);
                pojoImport.append(";");
                pojoImport.append(System.lineSeparator());
            }
        }
        dataMap.put("pojoImport", pojoImport.toString());
    }

    /**
     * 构造数据库数据map
     *
     * @param tableName
     * @return
     * @throws Exception
     */
    protected Map<String, Object> buildDatabaseDataMap(String tableName) throws Exception {
        Map<String, Object> map = new HashMap<>(2);
        TableData tableData = DatabaseUtil.getTableData(tableName);
        map.put("table", tableData);
        map.put("fieldList", tableData.getFieldList());
        return map;
    }
}
